<template>
  <transition name="fade">
    <div v-if="visible" class="opening">
      <canvas ref="canvasRef" class="webgl" />
      <div class="brand" ref="brandRef">SHU AI</div>
      <div class="hint" ref="hintRef">Scroll to enter</div>
      <button class="skip-btn" @click="end" title="跳过动画">跳过</button>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref } from 'vue'
import * as THREE from 'three'
import gsap from 'gsap'

const canvasRef = ref<HTMLCanvasElement | null>(null)
const brandRef = ref<HTMLDivElement | null>(null)
const hintRef = ref<HTMLDivElement | null>(null)
const visible = ref(true)

let renderer: THREE.WebGLRenderer | null = null
let scene: THREE.Scene | null = null
let camera: THREE.PerspectiveCamera | null = null
let animationId = 0
let mesh: THREE.Mesh | null = null
let timeline: gsap.core.Timeline | null = null

const dispose = () => {
  cancelAnimationFrame(animationId)
  timeline?.kill()
  renderer?.dispose()
  scene = null
  camera = null
  mesh = null
}

const end = () => {
  if (!visible.value) return
  gsap.to(camera!.position, {
    z: 8,
    duration: 1,
    ease: 'power3.in',
  })
  timeline?.reverse().then(() => {
    visible.value = false
    setTimeout(dispose, 600)
  })
}

onMounted(() => {
  const canvas = canvasRef.value!
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x0f0f0f)

  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 100)
  camera.position.set(0, 0, 8)

  renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true })
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
  renderer.setSize(window.innerWidth, window.innerHeight)

  const geometry = new THREE.IcosahedronGeometry(1.1, 1)
  const material = new THREE.MeshStandardMaterial({
    color: 0xff7a00,
    metalness: 0.2,
    roughness: 0.4,
  })
  mesh = new THREE.Mesh(geometry, material)
  mesh.scale.set(0, 0, 0)
  scene.add(mesh)

  const wire = new THREE.LineSegments(
    new THREE.WireframeGeometry(geometry),
    new THREE.LineBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.5 }),
  )
  mesh.add(wire)

  const light1 = new THREE.DirectionalLight(0xffffff, 0.8)
  light1.position.set(2, 2, 2)
  scene.add(light1)
  const light2 = new THREE.DirectionalLight(0xff7a00, 0.6)
  light2.position.set(-2, -1, 1)
  scene.add(light2)

  const onResize = () => {
    if (!renderer || !camera) return
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
  }
  window.addEventListener('resize', onResize)

  const onWheelOnce = () => {
    window.removeEventListener('wheel', onWheelOnce)
    end()
  }
  setTimeout(() => window.addEventListener('wheel', onWheelOnce, { passive: true }), 50)

  timeline = gsap
    .timeline({
      onComplete: () => setTimeout(end, 800), // 缩短自动结束时间从 1500ms 到 800ms
    })
    .to(camera.position, {
      z: 4,
      duration: 1, // 缩短相机动画时间从 2s 到 1s
      ease: 'power3.out',
    })
    .to(
      mesh.scale,
      {
        x: 1,
        y: 1,
        z: 1,
        duration: 0.8, // 缩短缩放动画时间从 1.5s 到 0.8s
        ease: 'power3.out',
      },
      '-=0.8', // 调整时间偏移
    )
    .fromTo(
      brandRef.value,
      { opacity: 0, y: 20 },
      { opacity: 1, y: 0, duration: 0.6, ease: 'power2.out' }, // 缩短文字动画时间
      '-=0.5', // 调整时间偏移
    )
    .fromTo(
      hintRef.value,
      { opacity: 0, y: 10 },
      { opacity: 1, y: 0, duration: 0.6, ease: 'power2.out' }, // 缩短提示文字动画时间
      '-=0.4', // 调整时间偏移
    )

  const clock = new THREE.Clock()
  const tick = () => {
    const t = clock.getElapsedTime()
    if (mesh) {
      mesh.rotation.x = t * 0.2
      mesh.rotation.y = t * 0.4
    }
    renderer?.render(scene!, camera!)
    animationId = requestAnimationFrame(tick)
  }
  tick()
})

onBeforeUnmount(() => dispose())
</script>

<style scoped>
.opening {
  position: fixed;
  inset: 0;
  background: #0f0f0f;
  display: grid;
  place-items: center;
  z-index: 2000;
}

.webgl {
  width: 100%;
  height: 100%;
  display: block;
}

.brand {
  position: absolute;
  color: #ffffff;
  font-weight: 800;
  letter-spacing: 4px;
  font-size: 28px;
  user-select: none;
  /* GSAP will control the initial state */
  opacity: 0;
}

.hint {
  position: absolute;
  bottom: 40px;
  color: #a3a3a3;
  font-size: 12px;
  letter-spacing: 1px;
  /* GSAP will control the initial state */
  opacity: 0;
}

.fade-enter-active,
.fade-leave-active {
  transition:
    opacity 0.6s ease,
    transform 0.6s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.skip-btn {
  position: absolute;
  top: 20px;
  right: 20px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #ffffff;
  padding: 8px 16px;
  border-radius: 20px;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
}

.skip-btn:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.4);
  transform: translateY(-1px);
}
</style>
